﻿using HarfBuzzSharp;
using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Model;
using LightCAD.Runtime;
//using netDxf.Entities;
using SkiaSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using LightCAD.MathLib;

namespace LightCAD.Drawing.Actions
{
    public class DimAngularArcAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;
        private Vector2 StartPoint;
        private Vector2 EndPoint;
        private Vector2 OverPoint;
        private Vector2 CenterPoint;
        private List<LcLine> selectLines;

        static DimAngularArcAction()
        {
            CommandName = "DIMANGULARARC";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "DAN",
                Description = "DIMANGULARARC",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="选择圆弧、圆、直线或 <指定顶点>:" },
                    new LcCreateStep{ Name="Step1", Options="指定角的第二个端点:" },
                    new LcCreateStep{ Name="Step2", Options="选择第二条直线:" },
                    new LcCreateStep{ Name="Step3", Options="指定标注弧线位置或 [多行文字(M)/文字(T)/角度(A)/象限点(Q)]:" },
                }
            };
            
        }

        internal static void Initilize()
        {
            ElementActions.DimAngularArc = new DimAngularArcAction();
            LcDocument.ElementActions.Add(BuiltinElementType.DimAngularArc, ElementActions.DimAngularArc);
        }

        private PointInputer PointInputer { get; set; }
        public DimAngularArcAction() { }
        public DimAngularArcAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令 ：DAN");
        }
        private LcCreateMethod GetMethod(string method)
        {
            if (method == null) return CreateMethods[0];
            var getted= CreateMethods.FirstOrDefault((m) => m.Name == method);
            if (getted == null)
                return CreateMethods[0];
            else
                return getted;
        }
        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            //this.Segments = new List<RolineSegment>();
            var curMethod = SetCurMethod(CreateMethods, 0);
            var ElementInputer = new ElementInputer(this.docEditor);
            this.PointInputer = new PointInputer(this.docEditor);
            this.selectLines = new List<LcLine>();
        Step0:
            var step0 = SetCurStep(curMethod, 0);
            var result0 = await ElementInputer.Execute(step0.Options);
            if (ElementInputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.ValueX == null)
            {
                goto Step0;
            }
            else
            {
                LcElement element = (LcElement)result0.ValueX;
                StartPoint = (Vector2)result0.Extent;
                if (element is LcArc)
                {
                    var arc = (LcArc)element;
                    goto Step1;
                }
                else if (element is LcLine)
                {
                    var line = (LcLine)element;
                    selectLines.Add(line);
                    goto Step2;
                }
                else
                {
                    goto Step0;
                }
            }
        Step1:
            //var step1 = curMethod.Steps[1];
            //var result1 = await PointInputer.Execute(step1.Options);
            goto End;
        Step2:
            var step2 = SetCurStep(curMethod, 2);
            var result2 = await ElementInputer.Execute(step2.Options);
            if (ElementInputer.isCancelled) { this.Cancel(); return; }
            if (result2 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result2.ValueX == null)
            {
                goto Step2;
            }
            else
            {
                LcElement element = (LcElement)result2.ValueX;
                EndPoint = (Vector2)result2.Extent;
                if (element is LcLine)
                {
                    var line = (LcLine)element;
                    selectLines.Add(line);
                    this.CenterPoint = DimAngularArc.GetLineIntersection(selectLines[0], selectLines[1]);
                    if (this.CenterPoint == null) {
                        this.Cancel();
                        goto End;
                    }
                    goto Step3;
                }
                else
                {
                    goto Step2;
                }
            }
        Step3:
            var step3 = SetCurStep(curMethod, 3);
            var result3 = await PointInputer.Execute(step3.Options);
            if (PointInputer.isCancelled) { this.Cancel(); return; }
            if (result3 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result3.ValueX == null)
            {
                goto Step3;
            }
            else
            {
                OverPoint = (Vector2)result3.ValueX;
                CreateDimElement();
            }
            goto End;
        End:
            this.EndCreating();

        }
        private void CreateDimElement()
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("DAN");
            var DimAngulararc = doc.CreateObject<DimAngularArc>();
            DimAngulararc.selectLines = selectLines;
            DimAngulararc.Centerp = CenterPoint;
            DimAngulararc.Movep = OverPoint;
            DimAngulararc.LoadDimAngleProperty();
            doc.ModelSpace.InsertElement(DimAngulararc);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }


        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }



        public override void CreateElement(LcElement element, Matrix3 matrix)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, matrix);
            }
        }
        public override void CreateElement(LcElement element, Vector2 basePoint, double scaleFactor)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, basePoint, scaleFactor);
            }

        }
        public override void CreateElement(LcElement element, Vector2 basePoint, Vector2 scaleVector)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, basePoint, scaleVector);
            }

        }
        public override void Draw(SKCanvas canvas, LcElement element, Matrix3 matrix)
        {
            var dimangle = element as DimAngularArc;
            dimangle.LoadDimAngleProperty();
            var center = this.vportRt.ConvertWcsToScr(dimangle.Centerp).ToSKPoint();
            var move = this.vportRt.ConvertWcsToScr(dimangle.Movep).ToSKPoint();
            double radius = Math.Sqrt(Math.Pow(center.X - move.X, 2) + Math.Pow(center.Y - move.Y, 2));
            float x1 = (float)(center.X - radius);
            float y1 = (float)(center.Y - radius);
            float x2 = (float)(center.X + radius);
            float y2 = (float)(center.Y + radius);
            SKRect skrect = new SKRect(x1, y1, x2, y2);
            var pen = this.GetDrawPen(element);
            if (pen == Constants.defaultPen)
            {
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    canvas.DrawArc(skrect, (float)dimangle.StartAngle, (float)dimangle.MoveAngle, false, elePen);
                }
            }
            else {
                canvas.DrawArc(skrect, (float)dimangle.StartAngle, (float)dimangle.MoveAngle, false, pen);
            }
            using (var paint = new SKPaint())
            {
                double textlength = 1000;
                Vector2 direction = dimangle.Endp - dimangle.Startp;
                Vector2 lidisptpos = dimangle.Midp + (new Vector2(direction.X * textlength, direction.Y * textlength)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                var pathstart = this.vportRt.ConvertWcsToScr(dimangle.Midp).ToSKPoint();
                var pathend = this.vportRt.ConvertWcsToScr(lidisptpos).ToSKPoint();

                var fontManager = SKFontManager.Default;
                var emojiTypeface = fontManager.MatchCharacter('时');
                paint.TextSize = (float)(this.vportRt.Viewport.Scale * 200);
                paint.IsAntialias = false;
                paint.Color = new SKColor(0x42, 0x81, 0xA4);
                paint.IsStroke = false;
                paint.Typeface = emojiTypeface;

                var skpath = new SKPath();
                skpath.MoveTo(pathstart);
                skpath.LineTo((float)pathend.X, (float)pathend.Y);

                canvas.DrawTextOnPath(Math.Abs((int)dimangle.MoveAngle).ToString()+"°", skpath, 0, 0, paint);
            }
        }


        public override void DrawAuxLines(SKCanvas canvas)
        {
            var mp = this.vportRt.PointerMovedPosition.ToVector2d();
            var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
            #region 选中2条线画角度标注
            if (selectLines.Count == 2) {
                if (CenterPoint != null) {
                    DimAngularArc dimangle = new DimAngularArc();
                    dimangle.selectLines = selectLines;
                    dimangle.Centerp = CenterPoint;
                    dimangle.Movep = wcs_mp;
                    dimangle.LoadDimAngleProperty();
                    var center = this.vportRt.ConvertWcsToScr(dimangle.Centerp).ToSKPoint();
                    double radius = Math.Sqrt(Math.Pow(center.X - mp.ToSKPoint().X, 2) + Math.Pow(center.Y - mp.ToSKPoint().Y, 2));
                    float x1 = (float)(center.X - radius);
                    float y1 = (float)(center.Y - radius);
                    float x2 = (float)(center.X + radius);
                    float y2 = (float)(center.Y + radius);
                    SKRect skrect = new SKRect(x1, y1, x2, y2);
                    
                    canvas.DrawArc(skrect, (float)dimangle.StartAngle, (float)dimangle.MoveAngle, false, Constants.auxElementPen);

                }
            }
            #endregion
        }

        /// <summary>
        /// 三点确定角度
        /// </summary>
        /// <param name="startpoint"></param>
        /// <param name="centerpoint"></param>
        /// <param name="endpoint"></param>
        /// <param name="reversal">是否开启顺时针180为正，逆时针180为负,默认为逆时针负角度</param>
        /// <returns></returns>
        public double ThreePointGetAngle(Vector2 startpoint, Vector2 centerpoint, Vector2 endpoint, bool reversal = false)
        {
            double angle = 0;
            var so = new Vector2(startpoint.X - centerpoint.X, startpoint.Y - centerpoint.Y);
            var eo = new Vector2(endpoint.X - centerpoint.X, endpoint.Y - centerpoint.Y);
            var pddir = (so.X * eo.Y) - (so.Y * eo.X);
            angle = (so.Angle() - eo.Angle()) / Math.PI * 180;
            if (reversal)
            {
                angle = (so.Angle() + (pddir < 0 ? (2 * Math.PI - eo.Angle()) : -eo.Angle())) / Math.PI * 180;
            }

            return angle;
        }

        private void DrawAuxArc(SKCanvas canvas, DimAngularArc dimangle)
        {
            
        }

        private void DrawAuxLine(SKCanvas canvas, Vector2 p0, Vector2 p1)
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(sk_pre, sk_p, Constants.auxElementPen);
            //辅助曲线的颜色，包括辅助长度，辅助角度等
        }

        #region Grip
        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var dimangle = element as DimAngularArc;
            var grips = new List<ControlGrip>();
            var gripCenter = new ControlGrip
            {
                Element = dimangle,
                Name = "Center",
                Position = dimangle.Centerp
            };
            var gripStart = new ControlGrip
            {
                Element = dimangle,
                Name = "Start",
                Position = dimangle.Startp
            };
            var gripEnd = new ControlGrip
            {
                Element = dimangle,
                Name = "End",
                Position = dimangle.Endp
            };
            var gripArcMidp = new ControlGrip
            {
                Element = dimangle,
                Name = "ArcMidp",
                Position = dimangle.Midp
            };
            grips.Add(gripCenter);
            grips.Add(gripStart);
            grips.Add(gripEnd);
            grips.Add(gripArcMidp);
            return grips.ToArray();
        }
        private string _gripName;
        private Vector2 _position;
        private DimAngularArc _dimangle;

        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            _dimangle = element as DimAngularArc;

            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                
            }
        }


        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_dimangle == null) return;
        }

        #endregion

        public override List<PropertyObserver> GetPropertyObservers()
        {
            return new List<PropertyObserver>()
            {
                
            };
        }
    }
}
